<?php

namespace App\Services\Stats\User\Elasticsearch;

use App\Core\Traits\Numeral;
use App\Models\Elasticsearch\Log\Login;
use App\Models\Elasticsearch\Settlement\Info as SettlementInfo;
use App\Services\Traits\DatabaseElasticsearch;
use Helper\Timed;
use App\Services\Service;


class RetentionService extends service
{
	use DatabaseElasticsearch, Numeral;

	/**
	 * 留存统计天数
	 *
	 * @var int[]
	 */
	protected $days = [1, 2, 3, 7, 15, 30];

	/**
	 * 获取玩家人数
	 *
	 * @param int $timed
	 * @param string $platCode
	 * @param array $ids
	 * @return int
	 */
	protected function getSignUserCount(int $timed, array $ids, $request): int
	{

		$params = ['body' => ['size' => 0, 'track_total_hits' => false]];
		// 筛选【UID】
		$params['body']['query']['bool']['must'][] = [
			'range' => [
				'uid' => ['gte' => $ids['id_min'], 'lte' => $ids['id_max']]
			]
		];
		// 筛选【时间】
		$this->makeWhereParamDatetime($request, $params, 'login_time', 'datetime', null, $timed, time(), 'day', false, false);
		// 筛选【平台】
		$this->makeWhereParamOrg($request, $params);

		// 统计参数
		$params['body']['aggs'] = $this->makeDistinct('uid');

		$result = Login::search($params);

		// 查询数据
		return $result['aggregations']['distinct_uid']['value'] ?? 0;
	}

	/**
	 * 数据列表【游戏留存】
	 */
	public function game($request)
	{
		date_default_timezone_set(Timed::getTimezoneName());

		list($start_time, $end_time) = Timed::datetimeFormat($request,'datetime');

		$total = ($end_time - $start_time + 1) / 86400;

		$collection =  [];

		$end_time -= ($request->input('page', 1) - 1) * $request->input('page_size', 15) * 86400;
		$end_time = $end_time + 1 - 1 * 86400;

		for (; $start_time <= $end_time; $end_time -= 86400) {
			if(count($collection) >= $request->input('page_size', 15)) continue;
			$collection[]['timed'] = $end_time;
		}

		foreach ($collection as &$item){
			$ids = $this->getGameUserIds($item['timed'], $request);
			$ids = array_unique($ids);

			foreach ($this->days as $day) {
				$timedDay = $item['timed'] + ($day - 1) * 86400;

				//当日登录用户数量
				$item["drr_{$day}_num"] = is_null($ids) ? 0 : ($day == 1 ? count($ids) : $this->getGameUserCount($timedDay, $ids, $request));
			}
		}
		$collection[0]['drr_2_num'] = 0;
		// $collection[1]['drr_2_num'] = $collection[0]['drr_1_num'];
		return [
			$collection,
			$total
		];
	}

	/**
	 * 获取玩家ID列表
	 *
	 * @param int $timed
	 * @param string $platCode
	 * @return array
	 */
	protected function getGameUserIds(int $timed, $request): array
	{
		$params = ['body' => ['size' => 0, 'track_total_hits' => false]];
		// 筛选【状态】
		$this->makeWhere($params, 'status', SettlementInfo::STATUS_NORMAL);
		// 筛选【类型】
		$this->makeWhere($params, 'player_type', SettlementInfo::PLAYER_TYPE);
		// 筛选【时间】
		$this->makeWhereParamDatetime($request, $params, 'end_time', 'datetime', null, $timed, $timed + 86400, 'default', false);
		// 筛选【平台】
		$this->makeWhereParamOrg($request, $params);

		// 统计参数
		$params['body']['aggs'] = $this->makeGroup(['uid']);

		// 查询数据
		$buckets = SettlementInfo::search($params)['aggregations']['group']['buckets'];

		return array_column(array_column($buckets, 'key'), 'uid');
	}

	/**
	 * 获取玩家人数
	 *
	 * @param int $timed
	 * @param array $ids
	 * @return int
	 */
	protected function getGameUserCount(int $timed, array $ids, $request): int
	{
		$params = ['body' => ['size' => 0, 'track_total_hits' => false]];
		// 筛选【UID】
		$this->makeWhere($params, 'uid', $ids, 'terms');
		// 筛选【时间】
		$this->makeWhereParamDatetime($request, $params, 'end_time', 'datetime', null, $timed, time(), 'day', false, false);

		// 统计参数
		$params['body']['aggs'] = $this->makeDistinct('uid');
		// 查询数据
		return SettlementInfo::search($params)['aggregations']['distinct_uid']['value'];
	}
}
